`include "PRV564Config.v"
`include "PRV564Define.v"
//TODO BUS BROADCAST PROCESS
//TODO BUS WRITE PIPELINING
module FIB_BIU_L1I
#(parameter FIBID=8'h00)(
    // global input
    input GLBi_CLK,
    input GLBi_ARST,
    // master request
    output reg BIUo_WREN,
    output [7:0] BIUo_ID,
    output reg BIUo_REQ,
    output reg [7:0] BIUo_CMD,
    output reg [3:0] BIUo_BURST,
    output reg [3:0] BIUo_SIZE,
    output reg [`PADR-1:0] BIUo_ADDR,
    output [`XLEN-1:0] BIUo_DATA,
    // slave reply
    input BIUi_FULL,
    input BIUi_ACK,
    input BIUi_V,
    input[7:0] BIUi_ID,
    input[7:0] BIUi_RPL,
    input[`XLEN-1:0] BIUi_DATA,
    //Cache Controller Interface

    input single_read_req,	//请求读一次
    input seq_read_req,		//请求读一行
    input [3:0]seq_size,//包请求尺寸
    input [3:0]req_bsel,    
    input [`PADR-1:0]bus_addr,		
    output [63:0]bus_rdata,
    output [15:0]addr_count,//no value
    output data_valid,			//cache写
    output reg trans_error,
    output bus_trans_finish			//传输完成
);
    localparam IDLE = 3'h0;//nothing happening 
    localparam CMDO = 3'h1;//Command Out
    localparam PNDR = 3'h2;//Data pending read
    localparam WAIT = 3'h5;//Wait for handshake complete(request withdraw)
    reg [2:0]state;
    reg [15:0]datacnt;
    reg [2:0]state_next;
    reg [7:0]cmd_decode;

    wire recv_valid,tran_valid,broadcast_valid;
    wire bw_wen;
    wire [15:0]datcnt_valcmp;
    assign datcnt_valcmp=((17'h01 << BIUo_BURST)-1);
    assign recv_valid=(FIBID == BIUi_ID) & BIUi_V;
    assign broadcast_valid = (FIBID == 8'h00) & BIUi_V;//broadcast signal
    assign tran_valid=BIUi_ACK & !(BIUi_FULL);
    assign BIUo_ID=FIBID;
    assign data_valid= (state==PNDR) & (recv_valid & (BIUi_RPL==`FIB_RPL_TRDY | BIUi_RPL==`FIB_RPL_SEQ));
    assign BIUo_DATA = 64'hx;
    assign bus_rdata= BIUi_DATA;
    assign bus_trans_finish=(state_next==WAIT);

    assign addr_count=datacnt;
    always@(*)
    begin
        casez({single_read_req,seq_read_req})
            2'b10:cmd_decode=`FIB_CMD_SIGR;
            2'b01:cmd_decode=`FIB_CMD_SEQR;
            2'b00:cmd_decode=`FIB_CMD_NOOP;
            default: cmd_decode=`FIB_CMD_NOOP;
        endcase
    end
    // finite state Machine
    
    always @(posedge GLBi_CLK or posedge GLBi_ARST) 
    begin
        if (GLBi_ARST) 
        begin
            datacnt<=0;
            BIUo_REQ<=1'b0;
            BIUo_WREN<=1'b0;
        end
        else 
        begin
        case(state_next)
            IDLE:
            begin
                datacnt<=0;
                BIUo_REQ<=1'b0;
                BIUo_WREN<=1'b0;
            end
            CMDO:
            begin
                if(state == IDLE)
                begin
                    BIUo_CMD<=cmd_decode;
                    BIUo_BURST<=seq_size;
                    BIUo_SIZE<=req_bsel;//
                    BIUo_ADDR<=bus_addr;
                end
                else
                begin
                    BIUo_CMD<=BIUo_CMD;
                    BIUo_BURST<=BIUo_BURST;
                    BIUo_SIZE<=BIUo_SIZE;//
                    BIUo_ADDR<=BIUo_ADDR;
                end
                BIUo_REQ<=1'b1;
                BIUo_WREN<=1'b1;
            end
            PNDR:
            begin
                BIUo_REQ<=1'b0;
                datacnt<=datacnt+
                   {15'h0,(recv_valid & (BIUi_RPL==`FIB_RPL_TRDY | BIUi_RPL==`FIB_RPL_SEQ))};
                BIUo_WREN<=1'b0;
            end
            WAIT:
            begin
                datacnt<=0;
                BIUo_REQ<=1'b0;
                BIUo_WREN<=1'b0;
            end
            default:
            begin
                datacnt<=0;
                BIUo_REQ<=1'b0;
                $display("Where the heck is BIU in?\r\n");
                BIUo_WREN<=1'b0;
            end
        endcase
        end
    end

    always@(*)
    begin
        trans_error=1'b0;
        case(state)
            IDLE:
                if(cmd_decode!=`FIB_CMD_NOOP) 
                    state_next=CMDO;
                else 
                    state_next=IDLE;
            CMDO:
                if(BIUi_FULL | !BIUi_ACK)
                    state_next=CMDO;
                else state_next=PNDR;
            PNDR:
                if(recv_valid & BIUi_RPL==`FIB_RPL_IDLE)
                    state_next=CMDO;
                else if((recv_valid & (BIUi_RPL==`FIB_RPL_TRDY | BIUi_RPL==`FIB_RPL_TERR)) & 
                        (datacnt >= datcnt_valcmp))
                        begin
                            state_next=WAIT;
                            if( BIUi_RPL==`FIB_RPL_TERR)trans_error=1'b1;
                        end
                else state_next=PNDR; 
            WAIT:
                if(single_read_req | seq_read_req)
                    state_next=WAIT;
                else 
                    state_next=IDLE;
            default: 
                state_next=IDLE;
        endcase
    end

    always @(posedge GLBi_CLK or posedge GLBi_ARST) begin
        if (GLBi_ARST)
            state <= IDLE;
        else
            state <= state_next;
    end

endmodule
